#include <stdio.h>
#include <avr/interrupt.h>
#include "uart.h"
#include "e2prom.h"
#include "iolgt8f0xa.h"

#define _NOP() do { __asm__ __volatile__ ("nop"); } while (0) 
	
#define EECR_VALUE_ERASE	((1 << 4) | (1 << 2))
#define EECR_VALUE_WRITE	((1 << 5) | (1 << 2))
#define EECR_VALUE_READ		(1 << EERE)

	
int e2promWrite(uint16_t startAddress, const char *buffer, int lenb) {
	cli();
	while (lenb --) {
		// wait flash ready
		while (EECR & (1 << EEPE));
		
		EEAR = (startAddress & 0x1FF);
		EEDR = *buffer ++;
		EECR |= (1 << EEMPE);
		EECR |= (1 << EEPE);

		startAddress ++;
		
		while (EECR & (1 << EEPE));
	}
	sei();
	return 0;
}

int e2promRead(int startAddress, char *buffer, int lenb) {
	cli();
	while (lenb --) {
		// wait flash ready
		while (EECR & (1 << EEPE));
		EEAR = (startAddress & 0x1FF);
		EECR |= (1 << EERE);
		
		_NOP();
		_NOP();
		_NOP();
		_NOP();
		
		*buffer = EEDR;
		
		buffer ++;
		startAddress ++;
	}
	sei();
	return 0;
}

#define test_block_sizeb 16
void e2promTest() {
	char buffer[test_block_sizeb];
	int addr;
	int i, j;
	
	for(i = 0; i < sizeof(buffer); i ++) {
		buffer[i] = i;
	}
	
	for(i = 0; i < 16; i ++) {
		e2promWrite(addr + test_block_sizeb * i, buffer, sizeof(buffer));
	}
	
	for(i = 0; i < 16; i ++) {
		memset(buffer, 0, sizeof(buffer));
		e2promRead(addr + test_block_sizeb * i, buffer, sizeof(buffer));
		for(j = 0; j < test_block_sizeb; j ++) {
			kprintf("0x%02x ", buffer[j]);
		}
		kprintf("\r\n");
	}
}

#if (0)
#include <string.h>
void FlashMain(void) {
	uint16_t buffer[4] = {0x0001, 0x0002, 0x0003, 0x8579};
	uint16_t buffer2[4];

	kprintf("start read page 15 before erase...");
	memset(buffer2, 0xFF, sizeof(buffer));
	FlashRead(15 << 9, buffer2, sizeof(buffer2));
	kprintf("[0x%x][0x%x][0x%x][0x%x]\r\n", buffer2[0], buffer2[1], buffer2[2], buffer2[3]);
	
	kprintf("erase page 15...");
	FlashErase(15, 0);
	kprintf("done\r\n");	
	
	kprintf("start read page 15 after erase...");
	memset(buffer2, 0xFF, sizeof(buffer));
	FlashRead(15 << 9, buffer2, sizeof(buffer2));
	kprintf("[0x%x][0x%x][0x%x][0x%x]\r\n", buffer2[0], buffer2[1], buffer2[2], buffer2[3]);
	
	kprintf("start program page 15...");
	FlashWrite(15 << 9, buffer, sizeof(buffer));
	kprintf("done\r\n");
	
	kprintf("start read page 15 after program...");
	memset(buffer2, 0xFF, sizeof(buffer2));
	FlashRead(15 << 9, buffer2, sizeof(buffer2));
	kprintf("[0x%x][0x%x][0x%x][0x%x]\r\n", buffer2[0], buffer2[1], buffer2[2], buffer2[3]);
	
	WaitFlashReady();
}
#endif